package com.symaster.common.geom.util;

import java.util.ArrayList;
import java.util.List;

public class PolygonOutlineUtil {

    public PolygonOutlineUtil(List<Point2D> pList) {
        this.pList = pList;
    }

    //+
    public Point2D plus(Point2D left, Point2D right) {
        return new Point2D(left.x + right.x, left.y + right.y);
    }

    //-
    public Point2D reduce(Point2D left, Point2D right) {
        return new Point2D(left.x - right.x, left.y - right.y);
    }

    // value*
    public Double rideDouble(Point2D left, Point2D right) {
        return left.x * right.x + left.y * right.y;
    }

    //*
    public Point2D ride(Point2D left, Double value) {
        return new Point2D(left.x * value, left.y * value);
    }

    // 自定义的向量差乘运算符号 **
    public Double operator(Point2D left, Point2D right) {
        return left.x * right.y - left.y * right.x;
    }

    public final List<Point2D> pList; // 原始顶点坐标， 在initPList函数当中初始化赋值
    public List<Point2D> dpList = new ArrayList<>();// 边向量dpList［i＋1］－ dpLIst［i］ 在 initDPList函数当中计算后赋值
    public List<Point2D> ndpList = new ArrayList<>(); // 单位化的边向量， 在initNDPList函数当中计算后肤质，实际使用的时候，完全可以用dpList来保存他们
    public List<Point2D> newList = new ArrayList<>();  // 新的折线顶点，在compute函数当中，赋值


    // 初始化顶点队列
    // public void initPList(String str) {
    //     String[] split = str.split(";");
    //     for (String point : split) {
    //         String[] split1 = point.split(",");
    //         pList.add(new Point2D(Double.valueOf(split1[0]), Double.valueOf(split1[1])));
    //     }
    // }


    // 初始化dpList  两顶点间向量差
    public void initDPList() {
        System.out.println("计算两顶点间向量差:dpList");
        for (int index = 0; index < pList.size(); index++) {
            int i = index == pList.size() - 1 ? 0 : index + 1;
            dpList.add(reduce(pList.get(index == pList.size() - 1 ? 0 : index + 1), pList.get(index)));
        }
    }


    // 初始化ndpList，单位化两顶点向量差
    public void initNDPList() {
        System.out.println("开始计算单位化两顶点向量差:ndpList");
        for (int index = 0; index < dpList.size(); index++) {
            ndpList.add(ride(dpList.get(index), (1.0 / Math.sqrt(rideDouble(dpList.get(index), dpList.get(index))))));
        }
    }

    // 计算新顶点， 注意参数为负是向内收缩， 为正是向外扩张
    public List<Point2D> computeLine(Double dist) {
        System.out.println("开始计算新顶点");
        int count = pList.size();
        for (int index = 0; index < count; index++) {
            int startIndex = index == 0 ? count - 1 : index - 1;
            int endIndex = index;
            Double sina = operator(ndpList.get(startIndex), ndpList.get(endIndex));
            Double length = dist / sina;
            Point2D vector = reduce(ndpList.get(endIndex), ndpList.get(startIndex));
            newList.add(plus(pList.get(index), ride(vector, length)));
        }
        return newList;
    }

    // 整个算法的调用顺序
    public static void main(String[] args) {

        // PolygonOutlineUtil polygonOutlineUtil = new PolygonOutlineUtil();
        //
        // // String str = "30.280196656341005,101.70201860368253;31.17443221616588,102.44943223893644;31.612013574947458,105.5988347902894;30.606585065678747,105.95238883048297";
        // // polygonOutlineUtil.initPList(str);
        // polygonOutlineUtil.initDPList();// 0.005
        // polygonOutlineUtil.initNDPList();
        // List<Point2D> point2DS = polygonOutlineUtil.computeLine(0.01D);// 正数为外廓，负数为内陷
        // point2DS.forEach(e -> {
        //     System.out.println("{lat: " + e.x + ", lng: " + e.y + "},");
        // });
    }

    public static class Point2D {
        public double x = 0.0;
        public double y = 0.0;

        public Point2D(double x, double y) {
            this.x = x;
            this.y = y;
        }

        @Override
        public String toString() {
            return "Point2D{" +
                    "x=" + x +
                    ", y=" + y +
                    '}';
        }
    }

}
